﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ChoiceUseCase.cs" company="">
//   
// </copyright>
// <summary>
//   The choice use case.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Libium.UseCases
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    /// <summary>
    /// The choice use case.
    /// </summary>
    /// <typeparam name="T">
    /// </typeparam>
    public abstract class ChoiceUseCase<T> : UseCase, IChoiceUseCase
    {
        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="ChoiceUseCase{T}"/> class.
        /// </summary>
        /// <param name="parent">
        /// The parent. 
        /// </param>
        /// <param name="service">
        /// The service. 
        /// </param>
        public ChoiceUseCase(ICompoundUseCase parent, IUseCaseInstanceService service)
            : base(parent, service)
        {
        }

        #endregion

        #region Public Events

        /// <summary>
        ///   The selected value changed.
        /// </summary>
        public event Action<IChoiceUseCase> SelectedValueChanged;

        #endregion

        #region Public Properties

        /// <summary>
        ///   Gets the named values.
        /// </summary>
        public IEnumerable<INamedValue<T>> NamedValues
        {
            get
            {
                return GetValues();
            }
        }

        /// <summary>
        ///   Gets or sets the selected value.
        /// </summary>
        public T SelectedValue
        {
            get
            {
                return GetValue();
            }

            set
            {
                var v = GetValue();
                if (v.Equals(value))
                {
                    return;
                }

                SetValue(value);
                OnSelectedValueChanged();
                Modified = true;
            }
        }

        public string SelectedName
        {
            get
            {
                var item = NamedValues.FirstOrDefault(i => i.Value.Equals(SelectedValue));
                return item == null ? string.Empty : item.Name;
            }
        }

        #endregion

        #region Explicit Interface Properties

        /// <summary>
        ///   Gets the named values.
        /// </summary>
        IEnumerable<INamedValue> IChoiceUseCase.NamedValues
        {
            get
            {
                return NamedValues;
            }
        }

        /// <summary>
        ///   Gets or sets the selected value.
        /// </summary>
        object IChoiceUseCase.SelectedValue
        {
            get
            {
                return SelectedValue;
            }

            set
            {
                SelectedValue = (T)value;
            }
        }

        #endregion

        #region Methods

        /// <summary>
        ///   The get value.
        /// </summary>
        /// <returns> The <see cref="T" /> . </returns>
        protected abstract T GetValue();

        /// <summary>
        ///   The get values.
        /// </summary>
        /// <returns> The <see cref="IEnumerable" /> . </returns>
        protected abstract IEnumerable<INamedValue<T>> GetValues();

        /// <summary>
        ///   The on selected value changed.
        /// </summary>
        protected virtual void OnSelectedValueChanged()
        {
            Modified = true;

            if (SelectedValueChanged != null)
            {
                SelectedValueChanged(this);
            }
        }

        /// <summary>
        /// The set value.
        /// </summary>
        /// <param name="value">
        /// The value. 
        /// </param>
        protected abstract void SetValue(T value);

        #endregion
    }
}